﻿package com.zouloux.medias.sub 
{
	import com.greensock.TweenMax;
	import com.zouloux.core.debug.Debug;
	import flash.display.Sprite;
	import flash.filters.DropShadowFilter;
	import flash.filters.GlowFilter;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	
	/**
	 * ...
	 * @author ZoulouX
	 */
	public class SubTitleItem extends Sprite
	{
		/**
		 * Animation d'arrivée par défaut
		 */
		public static var DEFAULT_START_ANIMATION	:ESubTitleAnimation 	= new ESubTitleAnimation(ESubTitleAnimation.QUICK_FADE);
		
		/**
		 * Animation de fin par défaut
		 */
		public static var DEFAULT_END_ANIMATION		:ESubTitleAnimation 	= new ESubTitleAnimation(ESubTitleAnimation.QUICK_FADE);
		
		/**
		 * Activer le contour par défaut
		 */
		public static var ENABLE_DEFAULT_OUTLINE	:Boolean				= true;
		
		/**
		 * Activer l'ombre par défaut
		 */
		public static var ENABLE_DEFAULT_SHADOW		:Boolean				= true;
		
		/**
		 * La couleur du contour
		 */
		public static var OUTLINE_COLOR				:uint 					= 0x000000;
		
		/**
		 * La transparence du contour
		 */
		public static var OUTLINE_ALPHA				:Number 				= .4;
		
		/**
		 * La rigidité du contour
		 */
		public static var OUTLINE_HARDNESS			:Number 				= 200;
		
		/**
		 * La taille du contour
		 */
		public static var OUTLINE_SIZE				:Number 				= 1.5;
		
		/**
		 * La distance de l'ombre
		 */
		public static var SHADOW_DISTANCE			:Number 				= 1;
		
		/**
		 * L'angle de l'ombre
		 */
		public static var SHADOW_ANGLE				:Number 				= 90;
		
		/**
		 * La taille de l'ombre
		 */
		public static var SHADOW_SIZE				:Number 				= 6;
		
		/**
		 * L'épaisseur de l'ombre
		 */
		public static var SHADOW_STRENGHT			:Number 				= 0.7
		
		/**
		 * La durée d'affichage d'une lettre
		 */
		public static var LETTER_TIME				:Number 				= 0.07;
		
		/**
		 * Largeur minimale du chaps texte
		 */
		public static var DEFAULT_WIDTH				:Number					= 500;
		
		/**
		 * Durée minimale d'affichage du texte
		 */
		public static var MINIMUM_TIME				:Number					= 1.5;
		
		/**
		 * Couleur par défaut
		 */
		public static var DEFAULT_COLOR				:uint					= 0xFFEEAA;
		
		/**
		 * Typo par défaut
		 */
		public static var DEFAULT_FONT				:String					= "Arial";
		
		/**
		 * Utiliser les typos embarquées
		 */
		public static var EMBED_FONT				:Boolean				= true;
		
		/**
		 * Taille du texte par défaut
		 */
		public static var DEFAULT_SIZE				:Number					= 15;
		
		/**
		 * Alignement par défaut
		 */
		public static var DEFAULT_ALIGN				:String					= "center";
		
		/**
		 * Alignement par défaut
		 */
		public static var DEFAULT_DEBUG				:Boolean				= false;
		
		/**
		 * Largeur de la vidéo
		 */
		protected var _videoWidth					:Number					= 0;
		
		/**
		 * Hauteur de la vidéo
		 */
		protected var _videoHeight					:Number					= 0;
		
		/**
		 * Le contenu
		 */
		protected var _content						:String;
		
		/**
		 * Le textField
		 */
		protected var _textField					:TextField;
		
		/**
		 * Le textFormat
		 */
		protected var _textFormat					:TextFormat;
		
		/**
		 * L'objet contenant les paramètres
		 */
		protected var _parameters					:Object					= {};
		
		/**
		 * L'animation de début
		 */
		protected var _startAnimation				:ESubTitleAnimation		= DEFAULT_START_ANIMATION;
		
		/**
		 * L'animation de fin
		 */
		protected var _endAnimation					:ESubTitleAnimation		= DEFAULT_END_ANIMATION;
		
		/**
		 * Le délais d'affichage
		 */
		protected var _delay						:Number					= 0;
		
		/**
		 * La durée d'affichage
		 */
		protected var _time							:Number					= MINIMUM_TIME;
		
		/**
		 * Autorisation d'écourter la vie de ce sous-titre
		 */
		protected var _allowKill					:Boolean				= true;
		
		/**
		 * Autorisation d'écourter la vie de ce sous-titre
		 */
		public function get allowKill():Boolean { return _allowKill; }
		
		/**
		 * Largeur de la vidéo associée
		 */
		public function get videoWidth():Number { return _videoWidth; }
		public function set videoWidth(value:Number):void 
		{
			_videoWidth = value;
		}
		
		/**
		 * Hauteur de la vidéo associée
		 */
		public function get videoHeight():Number { return _videoHeight; }
		public function set videoHeight(value:Number):void 
		{
			_videoHeight = value;
		}
		
		
		/**
		 * 
		 * @param	pContent
		 * @param	pParameters
		 */
		public function SubTitleItem (pContent:String, pParameters:Object = null, pController:SubTitleController = null)
		{
			Debug.core(this, "", arguments);
			
			// Initialiser les filtres
			filters = [];
			
			// Vérifier si on a un controller associé
			if (pController != null)
			{
				// Enregistrer les dimensions de la vidéo
				_videoWidth = pController.videoWidth;
				_videoHeight = pController.videoHeight;
			}
			
			// Enregistrer les paramètres
			_content = pContent;
			
			// Initialiser le textField
			init();
			
			// Parser les paramètres
			parseParameters(pParameters == null ? {} : pParameters);
			
			// Démarrer
			start();
		}
		
		/**
		 * Initialiser l'affichage
		 */
		private function init ():void
		{
			Debug.core(this, "init");
			
			// Initialiser le textField
			_textField = new TextField();
			
			// Configurer
			_textField.width = DEFAULT_WIDTH;
			_textField.selectable = false;
			_textField.mouseEnabled = false;
			_textField.autoSize = TextFieldAutoSize.LEFT;
			_textField.wordWrap = true;
			_textField.multiline = true;
			_textField.embedFonts = EMBED_FONT;
			
			// Initialiser le textFormat
			_textFormat = new TextFormat();
			_textFormat.size = DEFAULT_SIZE;
			_textFormat.color = DEFAULT_COLOR;
			_textFormat.align = DEFAULT_ALIGN;
			_textFormat.font = DEFAULT_FONT;
			
			// Ajouter le textField à ce clip
			addChild(_textField);
		}
		
		/**
		 * Parser les paramètres
		 */
		private function parseParameters (pParameters:Object):void
		{
			Debug.core(this, "parseParameters");
			
			// Ajouter du temps selon le contenu
			_time += _content.length * LETTER_TIME;
			
			// Configurer la largeur du texte en premier
			if (pParameters.width != null)
				_textField.width = parseInt(pParameters.width, 10);
			
			// Les paramètres par défaut
			if (pParameters.x == null)
				pParameters.x = "center";
			if (pParameters.y == null)
				pParameters.y = "bottom";
			if (pParameters.outline == null && ENABLE_DEFAULT_OUTLINE)
				pParameters.outline = "true";
			if (pParameters.shadow == null && ENABLE_DEFAULT_SHADOW)
				pParameters.shadow = "true";
			if (DEFAULT_DEBUG)
				pParameters.debug = "true";
			
			// Parser tous les paramètres
			for (var i:String in pParameters)
			{
				// Récupérer la valeur
				var value:String = pParameters[i];
				
				// Vérifier tous les types de paramètres possibles
				if (i == "x")
				{
					// La position en X
					if (value == "center")
						x = _videoWidth / 2 - _textField.width / 2;
					else
						x = parseInt(value, 10);
					
					// Ne plus autoriser à tuer
					_allowKill = false;
				}
				else if (i == "y")
				{
					// La position en Y
					if (value == "center")
						y = _videoHeight / 2 - _textField.height / 2;
					else if (value == "bottom")
						y = _videoHeight - _textField.height - 10;
					else if (value == "top")
						y = 10;
					else
						y = parseInt(value, 10);
					
					// Ne plus autoriser à tuer
					_allowKill = false;
				}
				else if (i == "color")
				{
					// La couleur du texte
					_textFormat.color = parseInt("0x" + value.substr(1, value.length), 16);
				}
				else if (i == "font")
				{
					// La typo
					_textFormat.font = value;
				}
				else if (i == "align")
				{
					// Alignement du texte
					_textFormat.align = value;
				}
				else if (i == "size")
				{
					// La taille du texte
					_textFormat.size = parseInt(value, 10);
				}
				else if (i == "start")
				{
					// L'animation de début
					_startAnimation = new ESubTitleAnimation(value);
				}
				else if (i == "end")
				{
					// L'animation de fin
					_endAnimation = new ESubTitleAnimation(value);
					
					// Ne plus autoriser à tuer
					_allowKill = false;
				}
				else if (i == "delay")
				{
					// Le décalage (en secondes)
					_delay = parseFloat(value);
				}
				else if (i == "time")
				{
					// La durée (en secondes)
					_time = parseFloat(value);
					
					// Ne plus autoriser à tuer
					_allowKill = false;
				}
				else if (i == "rotation")
				{
					// Appliquer la rotation
					rotation = parseInt(value, 10);
					
					// Ne plus autoriser à tuer
					_allowKill = false;
				}
				else if (i == "outline")
				{
					// Vérifier si on doit ajouter le contour
					if (value.toLowerCase() == "true" || value == "1")
						addOutline();
				}
				else if (i == "shadow")
				{
					// Vérifier si on doit ajouter l'ombre
					if (value.toLowerCase() == "true" || value == "1")
						addShadow();
				}
				else if (i == "debug")
				{
					// Vérifier si on doit ajouter une bordure
					if (value.toLowerCase() == "true" || value == "1")
					{
						_textField.border = true;
						_textField.borderColor = 0xFF0000;
					}
				}
			}
			
			// Actualiser le textFormat
			_textField.defaultTextFormat = _textFormat;
			
			// Appliquer le contenu
			_textField.htmlText = _content;
		}
		
		/**
		 * Ajouter de l'ombre
		 */
		protected function addShadow ():void
		{
			var tab:Array = filters;
			tab.push(new DropShadowFilter(SHADOW_DISTANCE, SHADOW_ANGLE, 0, 1, SHADOW_SIZE, SHADOW_SIZE, SHADOW_STRENGHT, 2));
			filters = tab;
		}
		
		/**
		 * Ajouter un contour
		 */
		protected function addOutline ():void
		{
			var tab:Array = filters;
			tab.unshift(new GlowFilter(OUTLINE_COLOR, OUTLINE_ALPHA, OUTLINE_SIZE, OUTLINE_SIZE, OUTLINE_HARDNESS, 2));
			filters = tab;
		}
		
		/**
		 * Démarrer
		 */
		protected function start ():void
		{
			Debug.core(this, "start");
			
			// Vérifier l'animation de début
			if (_startAnimation.isValid())
			{
				// Animation en fondu
				if (_startAnimation.value == ESubTitleAnimation.FADE)
				{
					TweenMax.from(this, .7, {
						alpha: 0,
						delay: _delay,
						onComplete: delayEndHandler
					});
				}
				else if (_startAnimation.value == ESubTitleAnimation.QUICK_FADE)
				{
					TweenMax.from(this, .35, {
						alpha: 0,
						delay: _delay,
						onComplete: delayEndHandler
					});
				}
				else
				{
					delayEndHandler();
				}
			}
			else if (_delay > 0)
			{
				// Masquer
				visible = false;
				
				// Utiliser le délais
				TweenMax.delayedCall(_delay, delayEndHandler);
			}
			else
			{
				delayEndHandler();
			}
		}
		
		/**
		 * Fin du délais
		 */
		protected function delayEndHandler():void
		{
			// Afficher
			visible = true;
			
			// Utiliser le délais pour mourir
			TweenMax.delayedCall(_time, kill, [false]);
		}
		
		/**
		 * Tuer ce clip
		 * @param	pInstant : Le faire instantanément, pas d'animation de fin
		 */
		public function kill (pInstant:Boolean = false):void
		{
			Debug.core(this, "kill");
			
			// Arrêter les tweens
			TweenMax.killTweensOf(this);
			
			// Vérifier si on doit terminer ce texte instantanément
			if (pInstant || !_endAnimation.isValid())
			{
				// Vérifier si le parent le contient bien
				if (parent != null && parent.contains(this))
					parent.removeChild(this);
			}
			else
			{
				// Animation en fondu
				if (_endAnimation.value == ESubTitleAnimation.FADE)
				{
					TweenMax.to(this, .7, {
						alpha: 0,
						onComplete: kill,
						onCompleteParams: [true]
					});
					_allowKill = false;
				}
				else if (_endAnimation.value == ESubTitleAnimation.QUICK_FADE)
				{
					TweenMax.to(this, .35, {
						alpha: 0,
						onComplete: kill,
						onCompleteParams: [true]
					});
				}
			}
		}
	}
}